package ir;

import java.util.ArrayList;
import java.util.List;

import run.Facet;

/**
 * IR Class representing Blocks in binding relationships in the statements.
 * For example:
 * 
 * .a						BLOCK.ONE_FACET
 * SQUARE					BLOCK.UNIT (UNIT.GENERIC) 
 * .in(SOMECELL).out		BLOCK.UNIT_FACET 
 * (.a, .b)					BLOCK.FACETS
 * INT:2					
 * .left(LESS_THAN:lt)
 * (.left(LESS_THAN:lt), .left(GREATER_THAN:gt)
 * 
 * among others.
 * 
 * @author Thomas Chau
 *
 */
public abstract class Block  {
	
	protected String type;
	
	protected ArrayList<CellUnit> units = new ArrayList<CellUnit>();
	protected ArrayList<Block> subblocks = new ArrayList<Block>();
	
	public void add(CellUnit u) {
		units.add(u);
	}
	
	public void add(Block b) {
		subblocks.add(b);
	}
	 
	public void setType(String blockType) {
		this.type = blockType;
	}

	/**
	 * Execution-stage method to retrieve the Block's left-eligible facets.
	 * Construct any cells necessary.
	 * @param structuralDefinition
	 * @return
	 */
	public abstract List<Facet> getLeftFacets(StructuralDefinition structuralDefinition) throws Exception;

	/**
	 * Execution-stage method to retrieve the Block's right-eligible facets.
	 * Construct any cells necessary.
	 * @param structuralDefinition
	 * @return
	 */
	public abstract List<Facet> getRightFacets(StructuralDefinition structuralDefinition) throws Exception;

	/**
	 * Performs a Symbol-Table like seek of a cell instance.
	 * @param labelName
	 * @return
	 */
	public CellUnit findInstance(String labelName) {
		
		for (CellUnit b : units) {
			if ( !(b instanceof InstanceRef) && labelName.equals(b.getLabel()))
				return b;
		}
		
		CellUnit candidate = null;
		for (Block b : subblocks) {
			candidate = b.findInstance(labelName);
			if (candidate != null)
				return candidate;
		}
		
		return candidate;
	}
	
	public String toString() {
		String s = "";
		for (CellUnit u : units)
			s += u.toString() + ",";
		for (Block b : subblocks)
			s += b.toString() + ",";
		return  s.substring(0, s.length() -1) ;
	}
	
	public Block getFirstSubBlock() {
		if (subblocks.size() == 1)
			return subblocks.get(0);
		else return null;
	}
	
	/** All blocks need to clone
	 */
	public abstract Block clone();
}
